package com.clp.protocol.iec104.apdu.asdu.info_obj.info_elem.file_transfer;

import com.clp.protocol.core.utils.ByteUtil;
import com.clp.protocol.iec104.definition.ConstVal;
import com.clp.protocol.iec104.definition.Ft;
import io.netty.buffer.ByteBuf;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;

import java.util.Arrays;
import java.util.Objects;

/**
 * 读文件数据传输 附加数据包
 */
@Getter
@NoArgsConstructor
@AllArgsConstructor
public class FileRDataRespAttachPack implements AttachPack {
    @Override
    public Ft.OperationTag operationTag() {
        return Ft.OperationTag.FILE_RDATA_RESP;
    }

    /**
     * 文件id
     */
    private long fileId;
    /**
     * 数据段号
     */
    private long dataSegment;
    /**
     * 后续标志
     */
    private Ft.FollowUpFlag followUpFlag;
    /**
     * 文件数据
     */
    private byte[] fileData;
    /**
     * 校验码
     */
    private int checkCode;

    @Override
    public FileRDataRespAttachPack initBy(ByteBuf buf) {
        checkOperationTag(buf.readByte());
        // 文件id
        byte[] fileIdBytes = new byte[ConstVal.FILE_ID_LEN]; buf.readBytes(fileIdBytes);
        this.fileId = ByteUtil.bytes4ToLongLE(fileIdBytes);
        // 数据段号
        byte[] dataSegmentBytes = new byte[ConstVal.DATA_SEGMENT_LEN]; buf.readBytes(dataSegmentBytes);
        this.dataSegment = ByteUtil.bytes4ToLongLE(dataSegmentBytes);
        // 后续标志
        this.followUpFlag = Ft.FollowUpFlag.gain(buf.readByte());
        // 文件数据
        this.fileData = new byte[buf.readableBytes() - 1]; buf.readBytes(fileData);
        // 校验码
        this.checkCode = buf.readByte();
        return this;
    }

    @Override
    public boolean isValid() {
        if (fileId < 0 || fileId > 0xFFFFFFFFL) return false;
        if (dataSegment < 0 || dataSegment > 0xFFFFFFFFL) return false;
        return followUpFlag != null;
    }

    @Override
    public void writeTo(ByteBuf buf) {
        // 填写操作标识
        buf.writeByte(operationTag().getVal());
        // 文件id
        buf.writeBytes(ByteUtil.longToBytes4LE(fileId));
        // 数据段号
        buf.writeBytes(ByteUtil.longToBytes4LE(dataSegment));
        // 后续标志
        buf.writeByte(followUpFlag.getVal());
        // 文件数据
        buf.writeBytes(fileData);
        // 校验码
        buf.writeByte(checkCode);
    }

    @Override
    public String toString() {
        return "文件id：" + fileId + ", 数据段号：" + dataSegment + ", " + "后续标志：" + followUpFlag
                + ", " + "文件数据：" + Arrays.toString(fileData) + ", 校验码：" + checkCode;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        FileRDataRespAttachPack that = (FileRDataRespAttachPack) o;
        return fileId == that.fileId && dataSegment == that.dataSegment && checkCode == that.checkCode && followUpFlag == that.followUpFlag && Arrays.equals(fileData, that.fileData);
    }

    @Override
    public int hashCode() {
        int result = Objects.hash(fileId, dataSegment, followUpFlag, checkCode);
        result = 31 * result + Arrays.hashCode(fileData);
        return result;
    }
}
